package main

import (
	"bytes"
	"html/template"
	"strings"
)

var tpl = `
type {{ .Name }}HttpServer struct {
	server {{ .Name }}Server
	
	router gin.IRouter
}czc.com/m/v2/

func Register{{ .Name }}HttpServer(server {{ .Name }}Server, router gin.IRouter) {
	// 我现在想用 gin.Default, 如果开发中我想使用其他的方式实例化gin
	g := &{{ .Name }}HttpServer{server: server, router: router}
	g.RegisterService()
}

{{ range .Methods }}
func (g *{{ $.Name }}HttpServer) {{ .HandlerName }}(ctx *gin.Context) {
	var in {{ .Request }}
	if err := ctx.BindJSON(&in); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	out, err := g.server.{{ .Name }}(ctx, &in)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	ctx.JSON(http.StatusOK, out)
}
{{ end }}

func (g *{{ .Name }}HttpServer) RegisterService() {
{{ range .Methods }}
	g.router.Handle("{{ .Method }}", "{{ .Path }}", g.{{ .HandlerName }})
{{ end }}
}
`

type serviceDesc struct {
	Name    string
	Methods []method
}

type method struct {
	Name    string
	Request string
	Reply   string

	// http rule
	Path   string
	Method string
	Body   string
}

func (m *method) HandlerName() string {
	return m.Name + "Gin"
}

func main() {
	// 模板
	buf := new(bytes.Buffer) // Buffer是一个可变大小的具有读和写方法的字节缓冲区。 Buffer的0值是一个可以使用的空缓冲区。
	// template.New("http") 创建了一个名为http的模板对象。该函数的参数是模板的名称，用于在后续的操作中引用该模板 在同一个程序中创建多个模板，可以使用不同的名称来标识它们
	// Parse 方法解析了一个模板字符串，并将其转换为模板对象。该方法的参数是包含模板内容的字符串
	tmpl, err := template.New("http").Parse(strings.TrimSpace(tpl))
	if err != nil {
		panic(err)
	}

	s := serviceDesc{
		Name: "Greeter",
		Methods: []method{
			{
				Name:    "SayHello",
				Request: "HelloRequest",
				Reply:   "HelloResponse",
				Path:    "/v1/sayhello",
				Method:  "POST",
				Body:    "*",
			},
		},
	}
	if err = tmpl.Execute(buf, s); err != nil {
		panic(err)
	}

	println(buf.String())
}
